package routes

import (
	"baize/app/business/monitor/monitorController"
	"baize/app/business/monitor/monitorService"
	"baize/app/business/system/systemController"
	"baize/app/business/tool/toolController"
	"baize/app/datasource/cache"
	"baize/app/datasource/objectFile/localhostObject"
	"bytes"
	"time"

	"github.com/baizeplus/sqly"
	"github.com/spf13/viper"
	swaggerFiles "github.com/swaggo/files"
	gs "github.com/swaggo/gin-swagger"

	"baize/app/middlewares"

	"baize/app/docs"
	"baize/app/setting"
	"baize/app/utils/logger"
	"net/http"
	"strings"

	"github.com/gin-contrib/cors"
	"github.com/google/wire"

	"github.com/gin-gonic/gin"
)

var ProviderSet = wire.NewSet(NewGinEngine)

func NewGinEngine(
	cache cache.Cache,
	ms sqly.SqlyContext,
	ls monitorService.IJobService,
	sc *systemController.System,
	mc *monitorController.Monitor,
	gc *toolController.Tool,
) *gin.Engine {

	if setting.Conf.Mode != "dev" {
		gin.SetMode(gin.ReleaseMode) // gin设置成发布模式
	}
	r := gin.New()
	r.Use(logger.NewLoggerMiddlewareBuilder().
		IgnorePaths("/ping").Build())
	r.Use(newCors())
	group := r.Group("")
	if setting.Conf.Mode == "dev" {
		host := setting.Conf.Host
		docs.SwaggerInfo.Host = host[strings.Index(host, "//")+2:]
		docs.SwaggerInfo.Schemes = []string{"http", "https"}
		group.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler))

		// 用我们自定义的暗黑模式 handler 替换原来的
		// group.GET("/swagger/*any", customSwaggerHandler())
	}

	//不做鉴权的
	{

		if viper.GetString("upload_file.type") == "local" {
			group.Static(localhostObject.ResourcePrefix, viper.GetString("upload_file.localhost.public_path"))
		}
		sc.Login.PublicRoutes(group) //登录
		sc.Sse.PublicRoutes(group)   //SSE链接

	}
	//做鉴权的
	group.Use(middlewares.NewSessionAuthMiddlewareBuilder(cache).Build(), middlewares.NewLoggerMiddlewareBuilder(ms).Build())
	{
		sc.Profile.PrivateRoutes(group)    //个人资料
		sc.Login.PrivateRoutes(group)      //登录
		sc.User.PrivateRoutes(group)       //用户
		sc.Dept.PrivateRoutes(group)       //部门
		sc.DictType.PrivateRoutes(group)   //字典类型
		sc.DictData.PrivateRoutes(group)   //地点数据
		sc.Role.PrivateRoutes(group)       //角色
		sc.Post.PrivateRoutes(group)       //岗位
		sc.Permission.PrivateRoutes(group) //岗位
		sc.Config.PrivateRoutes(group)     //配置
		sc.File.PrivateRoutes(group)       //文件
		sc.Notice.PrivateRoutes(group)     //消息
		sc.SelectBox.PrivateRoutes(group)
		mc.Server.PrivateRoutes(group)     //服务器详情
		mc.Oper.PrivateRoutes(group)       //操作日志
		mc.UserOnline.PrivateRoutes(group) //在线用户
		mc.Logfor.PrivateRoutes(group)     //登录日志
		mc.Job.PrivateRoutes(group)        //定时任务
		gc.GenTable.PrivateRoutes(group)   //代码生成
	}

	r.NoRoute(func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"msg": "404",
		})
	})
	//启动定时任务
	ls.InitJobRun()
	return r

}

func newCors() gin.HandlerFunc {
	ss := []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma", "FooBar"}
	config := cors.DefaultConfig()
	config.AllowOrigins = []string{"*"} //允许访问的域名
	config.AllowMethods = []string{"PUT", "PATCH", "GET", "POST", "DELETE", "OPTIONS"}
	config.AllowHeaders = []string{"*"}
	config.ExposeHeaders = ss
	config.MaxAge = time.Hour
	config.AllowCredentials = false
	return cors.New(config)

}

// 响应缓冲，用来捕获 Swagger HTML
// 实现 gin.ResponseWriter 接口
type responseBuffer struct {
	gin.ResponseWriter
	body       *bytes.Buffer
	headerSent bool // 标记响应头是否已发送
}

// 覆盖 Write 方法，强制把内容存到 buffer
func (w *responseBuffer) Write(b []byte) (int, error) {
	if !w.headerSent {
		w.headerSent = true
	}
	return w.body.Write(b)
}

// 覆盖 WriteHeader 方法，记录响应头状态
func (w *responseBuffer) WriteHeader(code int) {
	w.headerSent = true
	w.ResponseWriter.WriteHeader(code)
}

// 覆盖 Header 方法，转发响应头操作
func (w *responseBuffer) Header() http.Header {
	return w.ResponseWriter.Header()
}

// 新增：最终将 buffer 内容写入原响应
func (w *responseBuffer) Flush() {
	if w.body.Len() > 0 {
		w.ResponseWriter.Write(w.body.Bytes())
	}
}

// 自定义 Swagger Handler，注入暗黑模式 CSS + JS
func customSwaggerHandler() gin.HandlerFunc {
	swaggerHandler := gs.WrapHandler(swaggerFiles.Handler)

	return func(c *gin.Context) {
		// 只处理 index.html，其他资源（如 swagger-ui.css）直接放行
		if c.Request.URL.Path != "/swagger/index.html" {
			swaggerHandler(c)
			return
		}

		// 创建缓冲，准备捕获整个响应
		buf := &responseBuffer{
			ResponseWriter: c.Writer,
			body:           &bytes.Buffer{},
		}
		c.Writer = buf

		// 调用原 Swagger 处理器，生成 HTML
		swaggerHandler(c)

		// 读取捕获的 HTML（如果为空，直接返回原响应）
		html := buf.body.String()
		if html == "" {
			buf.Flush() // 确保内容写入原响应
			return
		}

		// 注入极简的暗黑模式代码（先测试基础功能）
		inject := `
		<style>
		body.dark { background: #1a1a2e; color: #e6e6e6; }
		</style>
		<script>
		document.addEventListener('DOMContentLoaded', () => {
			const btn = document.createElement('button');
			btn.innerText = '暗黑模式';
			btn.style.cssText = 'position:absolute;top:10px;right:10px;z-index:9999;';
			btn.onclick = () => document.body.classList.toggle('dark');
			document.body.appendChild(btn);
		});
		</script>`

		// 插入到 </head> 标签前
		html = strings.Replace(html, "</head>", inject+"</head>", 1)

		// 写入修改后的 HTML 到原响应
		c.Header("Content-Type", "text/html; charset=utf-8")
		c.Writer.Write([]byte(html))
	}
}
